Skip to content

Emulator streaming#3211

Open
LoneAngelFayt wants to merge 68 commits into
rommapp:masterfrom
LoneAngelFayt:feat/pcsx2-streaming-v2
Open

Emulator streaming#3211
LoneAngelFayt wants to merge 68 commits into
rommapp:masterfrom
LoneAngelFayt:feat/pcsx2-streaming-v2

Conversation

@LoneAngelFayt
Copy link
Copy Markdown
Contributor

@LoneAngelFayt LoneAngelFayt commented Apr 3, 2026

Overview

This PR adds a streaming framework to RomM that lets you launch games from the RomM UI into a native emulator running in a separate container. The stream comes back in the browser, with save state controls, volume, and session management built into the player.

The emulator runs in a linuxserver Docker container with a Selkies WebRTC stream. An HTTP broker sidecar inside that container handles game launches, archive extraction, and I/O. RomM talks to the broker through a new /api/streaming backend endpoint and embeds the stream in a player view.

Four emulators are covered here. More (PS3/rpcs3 and others) will follow in separate PRs once this lands.


Supported emulators

Platform slug Emulator Save states Slots Autosave slot Archive extraction
ps2 PCSX2 9 Slot 10 ❌ direct file only
ngc, wii, wiiu Dolphin 7 Slot 8 ❌ direct file only
xbox xemu 9 Slot 10 ❌ direct file only
switch Eden ❌ direct file only

Architecture

RomM frontend
  └── StreamingStore (Pinia)
        ├── fetchConfig()       — loads container list from backend on app start
        ├── claimSession()      — POST /api/streaming/sessions
        ├── saveState/loadState — proxied to broker via backend
        ├── saveAndExit()       — save + release session
        └── setVolume/setMute   — PulseAudio control via broker

RomM backend  (/api/streaming/*)
  ├── GET  /config              — returns enabled flag + container list
  ├── POST /sessions            — claims a session, proxies launch to broker
  ├── POST /sessions/{platform}/save-state
  ├── POST /sessions/{platform}/load-state
  ├── POST /sessions/{platform}/save-and-exit
  ├── POST /sessions/{platform}/volume
  ├── POST /sessions/{platform}/mute
  └── DELETE /sessions/{platform} — releases session

Emulator container (linuxserver + broker sidecar)
  ├── POST /launch              — kill current game, extract archive, launch
  ├── GET  /status              — session state + extraction progress (0–100%)
  ├── POST /save-state          — hotkey inject → poll for write confirmation
  ├── POST /load-state          — hotkey inject (fire-and-forget)
  ├── POST /save-and-exit
  ├── POST /volume              — pactl set-sink-volume
  └── POST /mute

Configuration (config.yml)

streaming:
  enabled: true
  containers:
    - platform: ps2
      host: https://192.168.1.51:3001       # Selkies WebRTC UI (browser-facing, must be HTTPS)
      broker_host: http://192.168.1.51:8000  # Broker API (server-to-container, HTTP ok)
      label: PCSX2
    - platform: ngc
      host: https://192.168.1.51:3002
      broker_host: http://192.168.1.51:8001
      label: Dolphin

Each emulator is its own container entry. Multiple platforms can share a container (e.g. ngc/wii/wiiu all pointing at the same Dolphin instance) or use separate ones. host is the URL the browser loads the stream from; broker_host is the server-side URL RomM uses to send commands.

Set a BROKER_SECRET env var on both the RomM container and the emulator container to authenticate broker API calls.


Changes

Backend

  • backend/endpoints/streaming.py — new router: session management, broker proxy, config endpoint
  • backend/config/config_manager.pySTREAMING_ENABLED + STREAMING_CONTAINERS config fields
  • backend/main.py — registers streaming router

Frontend

  • frontend/src/stores/streaming.ts — Pinia store: config, session lifecycle, per-platform capabilities
  • frontend/src/views/Player/Stream/Player.vue — streaming player view: Selkies iframe, loading overlay with extraction progress bar, save state controls, volume/mute
  • frontend/src/components/common/Game/PlayBtn.vue — "Play on [label]" button appears when a streaming container is configured for the platform
  • frontend/src/layouts/Main.vue — stream player route wired into nav
  • frontend/src/plugins/router.ts/play/:platform/:romId route

Config

  • examples/config.example.yml — streaming config example with comments
  • env.templateBROKER_SECRET variable

Broker containers

Each emulator has a companion Docker mod repo with the broker sidecar:

Each repo includes a docker-compose.yml showing the full setup.


UX flow

  1. User clicks Play on PCSX2 (the button only appears when a container is configured for that platform)
  2. RomM claims a session → broker kills any running game, extracts the archive if needed
  3. Loading overlay shows a spinner or extraction progress bar (0–100%) polled from /status
  4. Once running, the stream fills the player; save state controls and volume appear in the toolbar
  5. Save & Exit saves state, returns to the library, and releases the session for other users

AI Disclosure

Claude assisted in generating code and documentation.

@LoneAngelFayt
Copy link
Copy Markdown
Contributor Author

I've finished setting up the integration for dolphin as well, I'm going to split it out into a different PR for each integration

There is thankfully minimal changes but I turn some hardcoding into variables

Once you get done looking through this I'll adapt the others and put them in as I have them completed

@LoneAngelFayt LoneAngelFayt force-pushed the feat/pcsx2-streaming-v2 branch from 9c8da66 to 6a0e5ff Compare April 28, 2026 14:53
@LoneAngelFayt LoneAngelFayt changed the title feat: emulator streaming -- streaming framework and pcsx2 integration add emulator streaming Apr 28, 2026
@LoneAngelFayt
Copy link
Copy Markdown
Contributor Author

@gantoine I changed my mind, and just added all the emulators I've gotten working along with their respective changes.

I recruited Claude to help make my PR description a little better as well. Should outline everything I've touched and how it all works.

@gantoine gantoine added the on-hold Pending further research or blocked by another issue label Apr 29, 2026
@gantoine gantoine self-requested a review April 29, 2026 12:33
@gantoine gantoine changed the title add emulator streaming Emulator streaming May 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

on-hold Pending further research or blocked by another issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants